package com.gopay.scheduler.shedulerx.rdb;

import com.gopay.common.constants.scheduler.SchedulerConstants;
import com.gopay.scheduler.shedulerx.JobConfig;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 19371
 */
public class JobConfigRepository extends RdbConfigConstants implements JobRepository {
    
    private final static Logger LOGGER = LoggerFactory.getLogger(JobConfigRepository.class);

    private static JobConfigRepository repository = new JobConfigRepository();

    private JobConfigRepository() {
    }
    public static JobConfigRepository getSingle(){
        return repository;
    }

    /**
     * check init job configs
     * @param SIMPLE_JOB_MAP
     * @return
     */
    public Map<String,String> selectNeed2InitConfig(final HashMap<String,String> SIMPLE_JOB_MAP,String appName) throws SQLException {
        Map<String,String> needInitMap = new HashMap<>(SIMPLE_JOB_MAP.size());
        needInitMap.putAll(SIMPLE_JOB_MAP);
        String sql = String.format("SELECT job_name,cron_expression FROM %s where app_name='%s' ORDER BY region,job_name ASC ",GOPAY_JOB_CONFIG,appName);
        try (
                Connection conn = dataSource().getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql);
                ResultSet resultSet = preparedStatement.executeQuery()
        ) {
            while (resultSet.next()){
                String jobName = resultSet.getString(1);
                needInitMap.remove(jobName);
            }
        } catch (final SQLException ex) {
            errorLog(LOGGER," query fail，the method = {%s}","selectNeed2InitConfig",ex);
            throw ex;
        }
        return needInitMap;

    }

    /**
     * select all from gopay_job_config
     * @return
     */
    public List<JobConfig> selectJobConfig(String appName) throws SQLException {
        List<JobConfig> jobConfigs = new ArrayList<>();
        JobConfig jobConfig = null;
        String sql = String.format("SELECT job_id,app_name,job_name,cron_expression,job_class_name,decription,event_control,create_time,update_time, alarm,job_group,region FROM %s WHERE app_name= '%s' ",GOPAY_JOB_CONFIG,appName);
        try (
                Connection conn = dataSource().getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql);
                ResultSet resultSet = preparedStatement.executeQuery()
        ) {
            while (resultSet.next()){
                jobConfig = new JobConfig(resultSet.getString(1),resultSet.getString(2),resultSet.getString(3)
                        ,resultSet.getString(4),resultSet.getString(5),resultSet.getString(6),resultSet.getString(7),
                        resultSet.getTimestamp(8),resultSet.getTimestamp(9),resultSet.getString(10),resultSet.getString(11),
                        resultSet.getString(12));
                jobConfigs.add(jobConfig);
            }
        } catch (final SQLException ex) {
            errorLog(LOGGER," query fail，the method = {%s}","selectJobConfig",ex);
            throw ex;
        }
        return jobConfigs;

    }

    public List<JobConfig> selectJobConfigById(String jobId) throws SQLException {
        List<JobConfig> jobConfigs = new ArrayList<>();
        JobConfig jobConfig = null;
        String sql = String.format("SELECT job_id,app_name,job_name,cron_expression,job_class_name,decription,event_control,create_time,update_time, alarm,job_group,region FROM %s where job_id = '%s'",GOPAY_JOB_CONFIG,jobId);
        try (
                Connection conn = dataSource().getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql);
                ResultSet resultSet = preparedStatement.executeQuery()
        ) {
            while (resultSet.next()){
                jobConfig = new JobConfig(resultSet.getString(1),resultSet.getString(2),resultSet.getString(3)
                        ,resultSet.getString(4),resultSet.getString(5),resultSet.getString(6),resultSet.getString(7),
                        resultSet.getTimestamp(8),resultSet.getTimestamp(9),resultSet.getString(10),resultSet.getString(11),
                        resultSet.getString(12));
                jobConfigs.add(jobConfig);
            }
        } catch (final SQLException ex) {
            errorLog(LOGGER," query fail，the method = {%s}","selectJobConfigById",ex);
            throw ex;
        }
        return jobConfigs;

    }

    /**
     * insert to gopay_job_config
     * @param jobName
     * @param cronExpression
     * @return
     */
    public boolean insertJobConfig(String jobName,String cronExpression,String className,String group,String appName,String region,String description) throws SQLException {
        boolean execute = false;
        String sql = "INSERT INTO `" + GOPAY_JOB_CONFIG + "` (`job_name`,`app_name`, `cron_expression`, `job_class_name`, `decription`, `event_control`, `create_time`, `update_time`,`job_group`,`alarm`,`region`) "
                + "VALUES (?, ?, ?, ?, ?, ?, ?, ?,?,?,?);";
        try (
                Connection conn = dataSource().getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
            preparedStatement.setString(1, jobName);
            preparedStatement.setString(2, appName);
            preparedStatement.setString(3, cronExpression);
            preparedStatement.setString(4, className);
            preparedStatement.setString(5, description);
            preparedStatement.setString(6, SchedulerConstants.EVENT_CLOSE_TRACE);
            preparedStatement.setTimestamp(7,  new Timestamp(System.currentTimeMillis()));
            preparedStatement.setTimestamp(8, new Timestamp(System.currentTimeMillis()));
            preparedStatement.setString(9, group);
            preparedStatement.setString(10, SchedulerConstants.SCHEDULER_ALARM_NOMAL);
            preparedStatement.setString(11, region);
           preparedStatement.execute();
           execute =  true;
        } catch (final SQLException ex) {
            errorLog(LOGGER," insertConfig fail，the jobName = {%s}",jobName,ex);
            throw ex;
        }
        return execute;
    }

    public boolean updateJobConfig(JobConfig jobConfig){
        boolean execute = false;
            if(StringUtils.isBlank(jobConfig.getJobId())){
                return false;
            }
            int index = 1;
            StringBuilder sql = new StringBuilder();
            sql.append("UPDATE  ");
            sql.append(GOPAY_JOB_CONFIG).append(" SET update_time = ? ");
            if(StringUtils.isNotBlank(jobConfig.getDecription())){
                sql.append(", decription = ?");
            }
            if(StringUtils.isNotBlank(jobConfig.getAlarm())){
                sql.append(", alarm = ?");
            }
            if(StringUtils.isNotBlank(jobConfig.getEventControl())){
                sql.append(", event_control = ?");
            }
            sql.append(" WHERE job_id = ?");

        try (
                Connection conn = dataSource().getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql.toString())) {
                preparedStatement.setTimestamp(index++, new Timestamp(System.currentTimeMillis()));
                if(StringUtils.isNotBlank(jobConfig.getDecription())) {
                    preparedStatement.setString(index++, jobConfig.getDecription());
                }
                if(StringUtils.isNotBlank(jobConfig.getAlarm())) {
                    preparedStatement.setString(index++, jobConfig.getAlarm());
                }
                if(StringUtils.isNotBlank(jobConfig.getEventControl())) {
                    preparedStatement.setString(index++, jobConfig.getEventControl());
                }
                preparedStatement.setString(index++,jobConfig.getJobId());
                if(preparedStatement.executeUpdate() == 1){
                    return true;
                }else {
                    throw new SQLException("updateJobConfig fail");
                }
        } catch (final SQLException ex) {
            errorLog(LOGGER," updateJobConfig fail，the jobId = {%s}",jobConfig.getJobId(),ex);
        }
        return execute;
    }

    /**
     * insert to scheduler_crash_record
     * @param jobName
     * @param valueMap
     * @param createTime
     * @return
     */
    public boolean insertCrash(String jobName,Map<String, String> valueMap,Timestamp createTime,String appName,String region,String decription){
        boolean execute = false;
        String sql = "INSERT INTO `" + SCHEDULER_CRASH_RECORD + "` (`app_name`,`job_name`, `job_stat`, `job_update_time`, `create_time`,`juid`,`region`,`decription`) "
                + "VALUES (?, ?, ?, ?,?,?,?,?);";
        try (
                Connection conn = dataSource().getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
            preparedStatement.setString(1, appName);
            preparedStatement.setString(2, jobName);
            preparedStatement.setString(3, valueMap.get(SchedulerConstants.REDIS_STATE_MARK));
            preparedStatement.setString(4, valueMap.get(SchedulerConstants.REDIS_UPDATE_TIME_MARK));
            preparedStatement.setTimestamp(5, createTime);
            preparedStatement.setString(6, valueMap.get(SchedulerConstants.REDIS_UPDATE_JUID_MARK));
            preparedStatement.setString(7, region);
            preparedStatement.setString(8, decription);
            preparedStatement.execute();
            execute =  true;
        } catch (final SQLException ex) {
            errorLog(LOGGER," insertCrash fail，the jobName = {%s}",jobName,ex);
        }
        return execute;
    }
}
